#ifndef ZHY_MUDUO_BASE_BOUNDED_BLOCKINGQUEUE_H
#define ZHY_MUDUO_BASE_BOUNDED_BLOCKINGQUEUE_H

#include "Mutex.h"
#include "Condition.h"

#include <deque>

namespace _zhy_muduo
{
template<typename T>
class BoundedBlockingQueue
{
public:
	BoundedBlockingQueue(int maxSize)
		: mutex_(),
		notEmpty_(mutex_),
		notFull_(mutex_),
		kMaxSize_(maxSize),
		queue_()
	{}

	void put(const T& x)
	{
		MutexLockGuard lock(mutex_);
		while (queue_.size() == kMaxSize_) {
			notFull_.wait();
		}
		assert(kMaxSize_ > queue_.size());
		queue_.push_back(x);
		notEmpty_.notify();
	}

	void put(T&& x)
	{
		MutexLockGuard lock(mutex_);
		queue_.push_back(std::move(x));
		notEmpty_.notify();
	}

	T take()
	{
		MutexLockGuard lock(mutex_);
		while (queue_.empty()) {
			notEmpty_.wait();
		}
		assert(!queue_.empty());
		T front(std::move(queue_.front()));
		queue_.pop_front();
		notFull_.notify();
		return front;
	}

	bool empty() const
	{
		MutexLockGuard lock(mutex_);
		return queue_.empty();
	}

	bool full() const
	{
		MutexLockGuard lock(mutex_);
		return queue_.size() == kMaxSize_;
	}

	size_t size() const
	{
		MutexLockGuard lock(mutex_);
		return queue_.size();
	}
	
	size_t capacity() const
	{
		MutexLockGuard lock(mutex_);
		return (kMaxSize_ - queue_.size());
	}

	//zhy 
	void clear()
	{
		MutexLockGuard lock(mutex_);
		queue_.clear();
		notFull_.notify();
	}

private:
	mutable MutexLock mutex_;
	Condition notEmpty_;
	Condition notFull_;
	const size_t kMaxSize_;
	std::deque<T> queue_;
};
	//FIXME:disallow copy assign
}

#endif //ZHY_MUDUO_BASE_BOUNDED_BLOCKINGQUEUE_H
